import { useState, useEffect } from 'react';
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda.json';
import { CustomModelerForView } from '../InbizBpmn/Bpmn/customModeler';
import { getActivityInfo, getHighlightedNode, getProcessData } from './service';
import { setOverlaysHtmlToString, getOverlaysPosition } from './utils';
import './index.less';
import 'bpmn-js/dist/assets/diagram-js.css';

export default function BpmnViewer(props: any) {
    const { current = null, processId, instanceId, processLogData = [], isH5 = false } = props;
    const [customModelerForView, setCustomModelerForView] = useState<any>(null);
    const [nodeData, setNodeData] = useState<any>({});
    const [percent, setPercent] = useState(0.9);

    const getInitPreviewData = async (processId: string) => {
        const _nodeData = instanceId ? await getActivityInfo(instanceId) : {};
        setNodeData(_nodeData || {});
        const _highlightedData = instanceId ? await getHighlightedNode(instanceId) : {};
        const _processData = await getProcessData(processId);
        if (_processData?.code == '200' && _processData?.details?.processDefinitionXml) {
            const xmlForView = _processData?.details?.processDefinitionXml;
            const extPropForView = _processData?.details?.extProp;
            // @ts-ignore
            const bpmnModelerForView = new CustomModelerForView({
                container: '#processLogBpmnForView',
                height: '100%',
                additionalModules: [
                    {
                        zoomScroll: ['value', ''],
                        autoScroll: ['value', ''],
                        touch: ['value', ''],
                        move: ['value', ''],
                        labelEditingProvider: ['value', ''],
                        paletteProvider: ['value', ''],
                        alignElementsContextPadProvider: ['type', () => { }],
                        selectionVisuals: ['type', () => { }],
                        connectionSegmentMove: ['type', () => { }],
                        bendpointMove: ['type', () => { }],
                        contextPadProvider: ['type', () => { }],
                    },
                ],
                moddleExtensions: {
                    camunda: camundaModdleDescriptor,
                },
                // @ts-ignore
                bpmnRenderer: {
                    defaultStrokeColor: '#bbb',
                },
            });
            setCustomModelerForView(bpmnModelerForView);
            const data = extPropForView ? JSON.parse(extPropForView) : {};
            const CustomRenderer = bpmnModelerForView.get('customRenderer');
            CustomRenderer.userTaskData = data?.userTask || [];
            CustomRenderer.subProcessData = data?.callActivityTask || [];
            CustomRenderer.bpmnForView = true;
            CustomRenderer.activities = _highlightedData?.activities || [];
            CustomRenderer.currentNodeId = '';
            try {
                const result = await bpmnModelerForView.importXML(xmlForView);
            } catch (error) {
                console.log(error);
            };
            const Canvas = bpmnModelerForView.get('canvas');
            Canvas.zoom(0.9, { x: 0, y: 0 });
            // 画布右键无效
            const _canvas = document.getElementById('processLogBpmnForView');
            if (_canvas) {
                _canvas.addEventListener('contextmenu', (ev) => {
                    ev.preventDefault();
                });
            };
            const Modeling = bpmnModelerForView.get('modeling');
            const ElementRegistry = bpmnModelerForView.get('elementRegistry');
            if (_highlightedData?.flows) {
                _highlightedData?.flows?.forEach((item: string) => {
                    const _item = ElementRegistry.get(item);
                    Modeling?.setColor(_item, {
                        stroke: 'rgb(61, 200, 133)',
                    });
                });
            };
        };
    };

    // 初始数据
    useEffect(() => {
        if (processId) {
            getInitPreviewData(processId);
        };
    }, [processId]);

    // 节点渲染
    useEffect(() => {
        if (customModelerForView) {
            const CustomRenderer = customModelerForView?.get('customRenderer');
            const Modeling = customModelerForView?.get('modeling');
            const ElementRegistry = customModelerForView.get('elementRegistry');
            if (processLogData && processLogData?.length > 0) {
                const returnBackNodes = processLogData?.filter((item: { taskState: string | number }) => item?.taskState == '5');
                if (returnBackNodes?.length > 0) {
                    const returnBackNodeIds = returnBackNodes?.map((item: { task_Def_id: string; }) => item?.task_Def_id);
                    CustomRenderer.returnBackNodeIds = returnBackNodeIds;
                };
            };
            if (current) {
                CustomRenderer.currentNodeId = current?.task_Def_id;
            };
            const allInitElement = ElementRegistry.getAll();
            allInitElement?.forEach((item: any) => {
                Modeling.updateProperties(item, {});
            });
        };
    }, [current?.task_Def_id, processLogData, customModelerForView]);

    // 滚轮缩放
    useEffect(() => {
        if (customModelerForView) {
            const Canvas = customModelerForView.get('canvas');
            // @ts-ignore
            document.getElementById('processLogBpmnForView').addEventListener('wheel', (event) => {
                event.preventDefault();
                let _percent = percent;
                if (percent < 0.4 || percent > 2) {
                    return;
                };
                const delta = event.deltaY;
                if (delta > 0) {
                    _percent -= 0.1
                } else {
                    _percent += 0.1;
                };
                Canvas.zoom(_percent);
                setPercent(_percent);
            });
        };
    }, [customModelerForView, percent]);

    // hover节点
    useEffect(() => {
        if (customModelerForView && !isH5) {
            let overlaysData: any = {};
            const Overlays = customModelerForView.get('overlays');
            customModelerForView.on('element.hover', (event: any) => {
                const element = event?.element;
                const elementId = element?.id;
                const CustomRenderer = customModelerForView?.get('customRenderer');
                CustomRenderer.hoverNodeId = elementId;
                const Modeling = customModelerForView?.get('modeling');
                const ElementRegistry = customModelerForView.get('elementRegistry');
                const allInitElement = ElementRegistry.getAll();
                allInitElement?.forEach((item: any) => {
                    Modeling.updateProperties(item, {});
                });
                if (nodeData?.[elementId]) {
                    const hoverData = nodeData?.[elementId];
                    const _dom = setOverlaysHtmlToString(element, hoverData);
                    const overlaysId = Overlays.add(
                        element,
                        element?.type,
                        {
                            html: _dom,
                            show: {
                                minZoom: .4,
                                maxZoom: 2,
                            },
                            position: getOverlaysPosition(element),
                            scale: {
                                min: .4,
                                max: 2,
                            },
                        }
                    );
                    overlaysData[elementId] = overlaysId;
                };
            });
            customModelerForView.on('element.out', (event: any) => {
                const element = event?.element;
                const elementId = element?.id;
                if (overlaysData[elementId]) {
                    Overlays.remove(overlaysData[elementId])
                };
            });
        };
    }, [customModelerForView, nodeData, isH5]);

    return (
        <div className={'process-log-bpmn'} id='processLogBpmnForView' />
    )
}